class AsyncSeriesHook { // 钩子是同步的
  constructor(args) {
    this.tasks = []
  }
  tapPromise(name, task) {
    this.tasks.push(task)
  }

  async promise(...args) {
    let index = 0
    const next = (data) => {
      const task = this.tasks[index]
      if (!task) return Promise.reject()

      let res
      if (index === 0) {
        res = task(...args)
      } else {
        res =  task(data)
      }
      index++
      return res
    }

    return next()
      .then(data => next(data))
      .catch(err => err)
  }
}

const hook = new AsyncSeriesHook(['name'])
hook.tapPromise('react', function (name) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log('react', name)
      reject('错误')
    }, 1000)
  })
})

hook.tapPromise('node', function (data) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log('node', data)
      resolve()
    }, 3000);
  })
})

hook.promise('jw').then(function () {
  console.log('end');
})

// AsyncParallelBailHook 带保险异步并发的钩子